package com.zenithmind.disk.pojo.query;

import com.zenithmind.common.query.BaseQuery;
import com.zenithmind.disk.enums.FileStatus;
import com.zenithmind.disk.enums.FileType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 文件查询参数对象
 * 遵循单一职责原则：专注于文件查询条件的封装
 * 遵循开闭原则：通过方法封装便于扩展查询条件
 */
@EqualsAndHashCode(callSuper = true)
@Data
@Schema(description = "文件查询参数")
public class FileQuery extends BaseQuery {

    @Schema(description = "文件名（支持模糊查询）")
    private String fileName;

    @Schema(description = "用户ID")
    private String userId;

    @Schema(description = "父文件夹ID，null表示根目录")
    private String parentId;

    @Schema(description = "文件类型（MIME类型）")
    private String fileType;

    @Schema(description = "是否是文件夹 (0-文件, 1-文件夹)")
    private Integer isDirectory;

    @Schema(description = "状态 (0-删除, 1-正常)")
    private Integer status;

    @Schema(description = "文件扩展名")
    private String fileExtension;

    @Schema(description = "最小文件大小（字节）")
    private Long minFileSize;

    @Schema(description = "最大文件大小（字节）")
    private Long maxFileSize;

    @Schema(description = "创建时间开始")
    private LocalDateTime createTimeStart;

    @Schema(description = "创建时间结束")
    private LocalDateTime createTimeEnd;

    @Schema(description = "更新时间开始")
    private LocalDateTime updateTimeStart;

    @Schema(description = "更新时间结束")
    private LocalDateTime updateTimeEnd;

    @Schema(description = "是否加密 (0-未加密, 1-已加密)")
    private Integer isEncrypted;

    @Schema(description = "排序字段")
    private String sortField;

    @Schema(description = "排序方向 (ASC-升序, DESC-降序)")
    private String sortDirection;

    // ==================== 业务方法 ====================

    /**
     * 检查是否查询目录
     * @return true如果查询目录
     */
    public boolean isQueryingDirectories() {
        return isDirectory != null && isDirectory == 1;
    }

    /**
     * 检查是否查询文件
     * @return true如果查询文件
     */
    public boolean isQueryingFiles() {
        return isDirectory != null && isDirectory == 0;
    }

    /**
     * 检查是否在根目录查询
     * @return true如果在根目录查询
     */
    public boolean isQueryingRootDirectory() {
        return StringUtils.isBlank(parentId) || "root".equals(parentId);
    }

    /**
     * 检查是否有文件名过滤条件
     * @return true如果有文件名过滤
     */
    public boolean hasFileNameFilter() {
        return StringUtils.isNotBlank(fileName);
    }

    /**
     * 检查是否有文件大小过滤条件
     * @return true如果有文件大小过滤
     */
    public boolean hasFileSizeFilter() {
        return minFileSize != null || maxFileSize != null;
    }

    /**
     * 检查是否有时间范围过滤条件
     * @return true如果有时间范围过滤
     */
    public boolean hasTimeRangeFilter() {
        return createTimeStart != null || createTimeEnd != null ||
               updateTimeStart != null || updateTimeEnd != null;
    }

    /**
     * 获取文件状态枚举
     * @return 文件状态枚举
     */
    public FileStatus getFileStatus() {
        return status != null ? FileStatus.fromCode(status) : null;
    }

    /**
     * 设置文件状态
     * @param fileStatus 文件状态枚举
     */
    public void setFileStatus(FileStatus fileStatus) {
        this.status = fileStatus != null ? fileStatus.getCode() : null;
    }

    /**
     * 获取文件类型枚举
     * @return 文件类型枚举
     */
    public FileType getFileTypeEnum() {
        return isDirectory != null ? FileType.fromCode(isDirectory) : null;
    }

    /**
     * 设置文件类型
     * @param fileType 文件类型枚举
     */
    public void setFileTypeEnum(FileType fileType) {
        this.isDirectory = fileType != null ? fileType.getCode() : null;
    }

    /**
     * 设置查询目录
     */
    public void setQueryDirectories() {
        this.isDirectory = 1;
    }

    /**
     * 设置查询文件
     */
    public void setQueryFiles() {
        this.isDirectory = 0;
    }

    /**
     * 设置查询正常状态文件
     */
    public void setQueryNormalFiles() {
        this.status = FileStatus.NORMAL.getCode();
    }

    /**
     * 设置查询已删除文件
     */
    public void setQueryDeletedFiles() {
        this.status = FileStatus.DELETED.getCode();
    }

    /**
     * 设置文件大小范围
     * @param minSize 最小大小
     * @param maxSize 最大大小
     */
    public void setFileSizeRange(Long minSize, Long maxSize) {
        this.minFileSize = minSize;
        this.maxFileSize = maxSize;
    }

    /**
     * 设置创建时间范围
     * @param start 开始时间
     * @param end 结束时间
     */
    public void setCreateTimeRange(LocalDateTime start, LocalDateTime end) {
        this.createTimeStart = start;
        this.createTimeEnd = end;
    }

    /**
     * 设置更新时间范围
     * @param start 开始时间
     * @param end 结束时间
     */
    public void setUpdateTimeRange(LocalDateTime start, LocalDateTime end) {
        this.updateTimeStart = start;
        this.updateTimeEnd = end;
    }

    /**
     * 设置按文件名排序
     * @param ascending 是否升序
     */
    public void setSortByFileName(boolean ascending) {
        this.sortField = "fileName";
        this.sortDirection = ascending ? "ASC" : "DESC";
    }

    /**
     * 设置按文件大小排序
     * @param ascending 是否升序
     */
    public void setSortByFileSize(boolean ascending) {
        this.sortField = "fileSize";
        this.sortDirection = ascending ? "ASC" : "DESC";
    }

    /**
     * 设置按创建时间排序
     * @param ascending 是否升序
     */
    public void setSortByCreateTime(boolean ascending) {
        this.sortField = "createTime";
        this.sortDirection = ascending ? "ASC" : "DESC";
    }

    /**
     * 设置按更新时间排序
     * @param ascending 是否升序
     */
    public void setSortByUpdateTime(boolean ascending) {
        this.sortField = "updateTime";
        this.sortDirection = ascending ? "ASC" : "DESC";
    }

    /**
     * 检查排序方向是否为升序
     * @return true如果是升序
     */
    public boolean isSortAscending() {
        return "ASC".equalsIgnoreCase(sortDirection);
    }

    /**
     * 检查排序方向是否为降序
     * @return true如果是降序
     */
    public boolean isSortDescending() {
        return "DESC".equalsIgnoreCase(sortDirection);
    }

    /**
     * 设置查询图片文件
     */
    public void setQueryImageFiles() {
        setQueryFiles();
        // 可以在这里设置图片文件的MIME类型过滤
        this.fileType = "image/*";
    }

    /**
     * 设置查询视频文件
     */
    public void setQueryVideoFiles() {
        setQueryFiles();
        // 可以在这里设置视频文件的MIME类型过滤
        this.fileType = "video/*";
    }

    /**
     * 设置查询音频文件
     */
    public void setQueryAudioFiles() {
        setQueryFiles();
        // 可以在这里设置音频文件的MIME类型过滤
        this.fileType = "audio/*";
    }

    /**
     * 验证查询参数的有效性
     * @return true如果参数有效
     */
    public boolean isValid() {
        // 文件大小范围验证
        if (minFileSize != null && maxFileSize != null && minFileSize > maxFileSize) {
            return false;
        }

        // 时间范围验证
        if (createTimeStart != null && createTimeEnd != null && createTimeStart.isAfter(createTimeEnd)) {
            return false;
        }

        if (updateTimeStart != null && updateTimeEnd != null && updateTimeStart.isAfter(updateTimeEnd)) {
            return false;
        }

        // 排序字段验证
        if (StringUtils.isNotBlank(sortField)) {
            List<String> validSortFields = Arrays.asList("fileName", "fileSize", "createTime", "updateTime");
            if (!validSortFields.contains(sortField)) {
                return false;
            }
        }

        // 排序方向验证
        if (StringUtils.isNotBlank(sortDirection)) {
            if (!"ASC".equalsIgnoreCase(sortDirection) && !"DESC".equalsIgnoreCase(sortDirection)) {
                return false;
            }
        }

        return true;
    }

    /**
     * 重置查询条件
     */
    public void reset() {
        fileName = null;
        userId = null;
        parentId = null;
        fileType = null;
        isDirectory = null;
        status = null;
        fileExtension = null;
        minFileSize = null;
        maxFileSize = null;
        createTimeStart = null;
        createTimeEnd = null;
        updateTimeStart = null;
        updateTimeEnd = null;
        isEncrypted = null;
        sortField = null;
        sortDirection = null;
    }
}